﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Collections;

public class MyVector
{
    private int sid = -1;
    private ArrayList value; 
    private ArrayList iname;
    private ArrayList tag;
    public double norm = 0;

    public MyVector()
    {
        value = new ArrayList();
        iname = new ArrayList();
        tag = new ArrayList();
	}

    public MyVector(int sid)
    {
        this.sid = sid;
        value = new ArrayList();
        iname = new ArrayList();
        tag = new ArrayList();
        DBaccess db = new DBaccess();
        String sql = "select sid,cname,score from mr_recommand a,mr_course b where sid = '" + sid + "' and a.cid = b.cid";
        DataSet ds = db.GetDataSet(sql);
        for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
        {
            iname.Add(ds.Tables[0].Rows[i]["cname"].ToString());
            value.Add(Double.Parse(ds.Tables[0].Rows[i]["score"].ToString()));
            tag.Add(0);
        }
     }

    public int GetLength()
    {
        return value.Count;
    }

    public MyVector(int sid, ArrayList value, ArrayList iname, ArrayList tag)
    {
        this.sid = sid;
        if (value.Count == iname.Count && value.Count == tag.Count)
        {
            this.value = new ArrayList();
            this.iname = new ArrayList();
            this.tag = new ArrayList();
            for (int i = 0; i < value.Count; i++)
            {
                this.value.Add(value[i]);
                this.iname.Add(iname[i]);
                this.tag.Add(tag[i]);
            }
        }
    }

    public Double GetNorm()
    {
        return DotMultiply(this);
    }

    public Double DotMultiply(MyVector vec1)
    {
        double result = 0;
        if (value.Count != vec1.GetLength())
            return -1;
        for (int i = 0; i < value.Count; i++)
            result += GetValue(i) * vec1.GetValue(i);
        return result;
    }

    public Double GetValue(int index)
    {
         return Double.Parse(value[index].ToString());
    }

    public Double GetValue(String name)
    {
        int i = 0;
        for(i = 0; i < GetLength(); i++)
            if(GetIname(i) == name)
                return GetValue(i);
        return -1;
    }

    public void SetValue(double value, int index)
    {
        this.value[index] = value;
    }

    public void SetIname(String iname, int index)
    {
        this.iname[index] = iname;
    }
    
    public void SetTag(int tag, int index)
    {
        this.tag[index] = tag;
    }

    public int GetTag(int index)
    {
        return Int16.Parse(tag[index].ToString());
    }

    public Double GetAvg()
    {
        double avg = 0;
        for (int i = 0; i < this.GetLength(); i++)
            avg += GetValue(i);
        return avg / this.GetLength();
    }

    public ArrayList GetRank()
    {
        int i,j,k;
        double avg = 0,cont1 = 1, cont2 = -1;
        ArrayList rank = new ArrayList();
        for(i = 0; i < this.GetLength(); i++)
        {
            avg = 0;
            cont1 = 1;
            cont2 = -1;
            for(j = 0; j < this.GetLength(); j++)
            {
                if(GetValue(i) < GetValue(j))
                    cont1++;
                else if(GetValue(i) == GetValue(j))
                    cont2++;
            }
            for(k = 0; k < cont2; k++)
                avg+=cont2;
            rank.Add(cont1 + avg / 2);
        }
        return rank;
    }

    public String GetIname(int index)
    {
        return iname[index].ToString();
    }

    public int GetSid()
    {
        return sid;
    }

    public Double GetSim(MyVector vec)
    {
        int i = 0 ,j = 0;
        double avg1 = 0, avg2 = 0;
        double sim = 0;
        double numerator = 0, denominator1 = 0, denominator2 = 0;
        ArrayList rank1 = GetRank();
        ArrayList rank2 = vec.GetRank();
        for (i = 0; i < rank1.Count; i++)
            avg1 += Double.Parse(rank1[i].ToString());
        avg1 /= rank1.Count;
        for (i = 0; i < rank2.Count; i++)
            avg2 += Double.Parse(rank2[i].ToString());
        avg2 /= rank2.Count;
        for (i = 0; i < rank1.Count; i++)
        {
            for (j = 0; j < rank2.Count; j++)
            {
                if (GetIname(i) == vec.GetIname(j))
                    numerator += (Double.Parse(rank1[i].ToString()) - avg1) * (Double.Parse(rank2[j].ToString()) - avg2);
            }
            denominator1 += (Double.Parse(rank1[i].ToString()) - avg1) * (Double.Parse(rank1[i].ToString()) - avg1);
        }
        for (i = 0; i < rank2.Count; i++)
            denominator2 += (Double.Parse(rank2[i].ToString()) - avg2) * (Double.Parse(rank2[i].ToString()) - avg2);
        sim = numerator / Math.Sqrt(denominator1 * denominator2);
        return sim;
    }

    public ArrayList GetRest()
    {
        DBaccess db = new DBaccess();
        String sql = "select cname from mr_course where cid not in (select cid from mr_recommand where sid = '" + sid + "')";
        DataSet ds = db.GetDataSet(sql);
        ArrayList inametmp = new ArrayList();
        for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
            inametmp.Add(ds.Tables[0].Rows[i]["cname"]);
        return inametmp;
    }

    public bool Contains(String name)
    {
        for(int i = 0; i < GetLength(); i++)
            if(GetIname(i) == name)
                return true;
        return false;
    }


    public ArrayList GetRelate(double sim, String name)
    {
        ArrayList mvArr = new ArrayList();
        DBaccess db = new DBaccess();
        String sql = "select sid from mr_v_recommand where sid != '" + sid + "'";
        DataSet ds = db.GetDataSet(sql);
        int i = 0;
        ArrayList tmp = new ArrayList();
        ArrayList rest = GetRest();
        for (i = 0; i < ds.Tables[0].Rows.Count; i++)
        {
            tmp.Add(new MyVector(Int16.Parse(ds.Tables[0].Rows[i]["sid"].ToString())));
            if (((MyVector)tmp[i]).Contains(name) && (GetSim(((MyVector)tmp[i]))) > sim)
                mvArr.Add(((MyVector)tmp[i]));
        }
        return mvArr;
    }

    public String Show()
    {
        String output = "";
        for (int i = 0; i < GetLength(); i++)
        {
            output += GetIname(i) + ":" + GetValue(i).ToString("0.00") + " ";
            if (Int16.Parse(tag[i].ToString()) == 0)
                output += "(原有的) ";
            else
                output += "(推荐的) ";
        }
        output += "<br>";
        return output;
    }

    public void AddVector(double value, String name, int tag)
    {
        this.value.Add(value);
        this.iname.Add(name);
        this.tag.Add(tag);
    }

    public void Recommand(double sim)
    {
        int i, j;
        double numerator = 0 , denominator = 0;
        for (j = 0; j < GetRest().Count; j++)
        {
            String nametmp = GetRest()[j].ToString();
            ArrayList arr = GetRelate(sim, nametmp);
            for (i = 0; i < arr.Count; i++)
            {
                MyVector mv = (MyVector)arr[i];
                numerator += (mv.GetValue(nametmp) - mv.GetAvg()) * GetSim(mv);
                denominator += Math.Abs(GetSim(mv));
            }
            AddVector(GetAvg() + numerator / denominator, nametmp, 1);
        }
    }

    public MyVector GetRecommand()
    {
        int i;
        ArrayList valuetmp = new ArrayList();
        ArrayList inametmp = new ArrayList();
        ArrayList tagtmp = new ArrayList();
        for (i = 0; i < GetLength(); i++)
        {
            if (GetTag(i) == 1)
            {
                valuetmp.Add(GetValue(i));
                inametmp.Add(GetIname(i));
                tagtmp.Add(1);
            }
            else
                continue;
        }
        return new MyVector(GetSid(), valuetmp, inametmp, tagtmp);
    }

    public MyVector GetNoRecommand()
    {
        int i;
        ArrayList valuetmp = new ArrayList();
        ArrayList inametmp = new ArrayList();
        ArrayList tagtmp = new ArrayList();
        for (i = 0; i < GetLength(); i++)
        {
            if (GetTag(i) == 0)
            {
                valuetmp.Add(GetValue(i));
                inametmp.Add(GetIname(i));
                tagtmp.Add(0);
            }
            else
                continue;
        }
        return new MyVector(GetSid(), valuetmp, inametmp, tagtmp);
    }

    public void Sort()
    {
        int i ,j ,tagtmp;
        String inametmp;
        ArrayList valuetmp = new ArrayList(value);
        value.Sort();
        value.Reverse();
        for(i = 0; i < GetLength(); i++)
            for(j = i; j < GetLength(); j++)
                if (value[i] == valuetmp[j])
                {
                    inametmp = iname[j].ToString();
                    iname.RemoveAt(j);
                    iname.Insert(i, inametmp);
                    tagtmp = Int16.Parse(tag[j].ToString());
                    tag.RemoveAt(j);
                    tag.Insert(i, tagtmp);
                    valuetmp.RemoveAt(j);
                    valuetmp.Insert(i, value[i]);
                }
    }
}